package com.nx.platform.es.bean.modle.param;

import com.google.common.base.Enums;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Table;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.nx.platform.es.bean.dto.RequestContext;
import com.nx.platform.es.biz.wrapper.parser.StatementOperator;
import com.nx.platform.es.common.utils.MoreSplitters;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.elasticsearch.common.Strings;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author
 * @since 2016年10月15日
 */
public class NumberSetHandler implements ParamFieldHandler {

    @Override
    public void handle(RequestContext context, ImmutableMap<String, ?> fieldConfig,
                       Table<String, StatementOperator, List<String>> queryTable,
                       Table<String, StatementOperator, List<String>> paramsTable, Map<String, Object> paramsMap) {
        String fieldFace = MapUtils.getString(fieldConfig, "face");
        if (Strings.isNullOrEmpty(fieldFace)) {
            return;
        }
        final String clazz = MapUtils.getString(fieldConfig, "class");
        List<String> fieldValues = paramsTable.get(fieldFace, StatementOperator.EQUAL);
        if (CollectionUtils.isEmpty(fieldValues)) {
            return;
        }
        String fieldValue = fieldValues.get(0);
        if (Strings.isNullOrEmpty(fieldValue)) {
            return;
        }
        List<Comparable<? extends Number>> param = MoreSplitters.VERTICAL.splitAsStream(fieldValue)
                .map(String::trim).map(e -> parse(clazz, e)).filter(Objects::nonNull)
                .distinct().sorted().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(param)) {
            context.getTrace().append("&_param_").append(fieldFace).append(StatementOperator.EQUAL.getSymbol())
                    .append(Joiner.on('|').join(param));
            paramsMap.put(fieldFace, param);
        }
    }

    protected Comparable<? extends Number> parse(String clazz, String str) {
        return Enums.getIfPresent(Parsers.class, clazz).or(Parsers.Long).parse(str);
    }

    enum Parsers {
        Byte {
            @Override
            Comparable<? extends Number> parse(String str) {
                try {
                    return java.lang.Byte.parseByte(str);
                } catch (NumberFormatException nfe) {
                    return null;
                }
            }
        },
        Short {
            @Override
            Comparable<? extends Number> parse(String str) {
                try {
                    return java.lang.Short.parseShort(str);
                } catch (NumberFormatException nfe) {
                    return null;
                }
            }
        },
        Interger {
            @Override
            Comparable<? extends Number> parse(String str) {
                return Ints.tryParse(str);
            }
        },
        Long {
            @Override
            Comparable<? extends Number> parse(String str) {
                return Longs.tryParse(str);
            }
        };

        abstract Comparable<? extends Number> parse(String str);

    }

}
